/**
 - ECMA-262 把原型链定义为 ECMAScript 的主要继承方式。
 - 构造函数、原型和实例的关系：每个构造函数都有一个原型对象，原型有一个属性指回构造函数，而实例有一个内部指针指向原型。
 */
;(function () {
    function SuperType() {
        this.property = true;
    }

    SuperType.prototype.getSuperValue = function () {
        return this.property;
    };

    function SubType() {
        this.subproperty = false;
    }

// 继承 SuperType
    SubType.prototype = new SuperType();
    SubType.prototype.getSubValue = function () {
        return this.subproperty;
    };

    let instance = new SubType();
    console.log(instance.getSuperValue());
    console.log(instance.getSubValue())
})();


/**
 * 子类有时候需要覆盖父类的方法，或者增加父类没有的方法。为此，这些方法必须在原型赋值之后 再添加到原型上。
 */
;(function () {
    function SuperType() {
        this.property = true
    }

    SuperType.prototype.getSuperValue = function () {
        return this.property
    }

    function SubType() {
        this.subProperty = false
    }

    // 继承 SuperType
    SubType.prototype = new SuperType()

    // 新方法
    SubType.prototype.getSubValue = function () {
        return this.subProperty
    }

    // 覆盖已有的方法
    SubType.prototype.getSuperValue = function () {
        return false
    }

    let instance = new SubType()
    console.log(instance.getSuperValue())

})();

/**
 * 特别重要:
 * 以对象字面量方式创建原型方法会破坏之前的原型链，因为这相当于重写 了原型链。
 */
;(function () {
    function SuperType() {
        this.property = true;
    }

    SuperType.prototype.getSuperValue = function () {
        return this.property;
    };

    function SubType() {
        this.subproperty = false;
    }

    // 继承 SuperType
    SubType.prototype = new SuperType();

    // 通过对象字面量添加新方法，这会导致上一行无效
    SubType.prototype = {
        getSubValue() {
            return this.subproperty
        },
        somOtherMethod() {
            return false
        }
    }

    let instance = new SubType();
    console.log(instance.getSuperValue())   // 出错!
})();